//
// Created by ziya on 2025/9/30.
//
#include "common.h"
#include "debugger.h"

/**
 *
 * @param p_pid parent
 * @param c_pid child
 */
static void debugger_core(pid_t p_pid, pid_t c_pid) {
    int wait_status;

    INFO_PRINT("parent pid: %d, child pid: %d\n", p_pid, c_pid);

    waitpid(c_pid, &wait_status, 0);

    // 处理子进程状态
    if (WIFEXITED(wait_status)) {
        printf("Child exited normally with exit code %d\n", WEXITSTATUS(wait_status));
    } else if (WIFSIGNALED(wait_status)) {
        printf("Child was terminated by signal %d\n", WTERMSIG(wait_status));
    } else if (WIFSTOPPED(wait_status)) {
        printf("Child was stopped by signal %d\n", WSTOPSIG(wait_status));
    } else if (WIFCONTINUED(wait_status)) {
        printf("Child was resumed by delivery of SIGCONT\n");
    }

    getchar();

    INFO_PRINT("debugger exit..\n");
}

static void run_exec(const char *exec_filename) {
    /* 子进程：让内核允许父进程跟踪自己，然后 exec */
    ptrace(PTRACE_TRACEME, 0, NULL, NULL);

    /* 触发 exec-stop，父进程会在 exec 完成前收到一次停止（SIGTRAP） */
    execl(exec_filename, exec_filename, NULL);

    /* 如果 execl 返回，说明失败 */
    perror("execl fail");
    exit(-1);
}

void debugger(const char *exec_filename) {
    pid_t pid;

    pid = fork();
    if (0 == pid) { // child
        run_exec(exec_filename);
    } else if (pid > 0) { // parent
        debugger_core(getpid(), pid);
    } else {
        // 如果fork失败
        perror("fork fail");
        exit(-1);
    }
}